iT邦幫忙

2024 iThome 鐵人賽

DAY 10
0
自我挑戰組

C# 和 SQL 探索之路 - 3系列 第 10

Day 10: C# 實作 SOLID 開發原則 2

  • 分享至 

  • xImage
  •  

接續昨天的文章,繼續來講剩下的原則 ~

L:Liskov 替換原則(Liskov Substitution Principle, LSP)

子類別可以替換父類別,而不會影響程式架構;子類別可以執行父類別想做的事。以下範例中,Square 繼承 Rectangle,但保持矩形的行為。

// Liskov 替換原則
public class Rectangle
{
    public virtual double Width { get; set; }
    public virtual double Height { get; set; }

    public double GetArea()
    {
        return Width * Height;
    }
}

public class Square : Rectangle
{
    private double side;

    public Square(double side)
    {
        this.side = side;
    }

    public override double Width
    {
        get { return side; }
        set { side = value; }
    }

    public override double Height
    {
        get { return side; }
        set { side = value; }
    }
}

I:介面隔離原則(Interface Segregation Principle, ISP)

避免將不相關的功能放到同一個介面中,應該將它們拆成多個專門的介面;簡單來說就是將不同功能分離至不同介面。以下範例中,我們將列印和儲存功能分離到不同介面。

// 介面隔離原則
public interface IPrintable
{
    void Print();
}

public interface ISavable
{
    void Save();
}

public class Report : IPrintable, ISavable
{
    public void Print()
    {
        Console.WriteLine("Printing Report...");
    }

    public void Save()
    {
        Console.WriteLine("Saving Report...");
    }
}

D: Dependency Inversion Principle (依賴反轉原則)

高階模組不應依賴低階模組,兩者都應依賴於抽象;避免父類別因為子類別改變而被迫改變。以下範例中,我們將依賴反轉,使 OrderProcessor 依賴於 IPaymentProcessor 介面,而不是具體的實作。

// 依賴反轉原則
public interface IPaymentProcessor
{
    void ProcessPayment(double amount);
}

public class PayPalPaymentProcessor : IPaymentProcessor
{
    public void ProcessPayment(double amount)
    {
        Console.WriteLine($"Processing PayPal payment of {amount}...");
    }
}

public class CreditCardPaymentProcessor : IPaymentProcessor
{
    public void ProcessPayment(double amount)
    {
        Console.WriteLine($"Processing credit card payment of {amount}...");
    }
}

public class OrderProcessor
{
    private IPaymentProcessor paymentProcessor;

    public OrderProcessor(IPaymentProcessor paymentProcessor)
    {
        this.paymentProcessor = paymentProcessor;
    }

    public void ProcessOrder(double amount)
    {
        paymentProcessor.ProcessPayment(amount);
    }
}

結論

用以下的程式呼叫上述類別:


public class Program
{
	public static void Main()
	{
		// Liskov 替換原則
        Rectangle rect = new Rectangle { Width = 5, Height = 10 };
        Square square = new Square(5);
        Console.WriteLine($"Rectangle area: {rect.GetArea()}");
        Console.WriteLine($"Square area: {square.GetArea()}");

        // 介面隔離原則
        Report report = new Report();
        report.Print();
        report.Save();

        // 依賴反轉原則
        IPaymentProcessor paymentProcessor = new PayPalPaymentProcessor();
        OrderProcessor orderProcessor = new OrderProcessor(paymentProcessor);
        orderProcessor.ProcessOrder(250.0);
	}
}

以上原則幫助你在寫出有彈性的程式,而且減少重複修改的機會,或是變成義大利麵般的雜亂!

參考資料

  • 個人 Github Pages
  • ChatGPT 產生部分程式碼

上一篇
Day 9: C# 實作 SOLID 開發原則 1
下一篇
Day 11: C# 實作表象模式
系列文
C# 和 SQL 探索之路 - 330
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言